class Solution {
    public boolean isPalindrome(String s) {
        // Time: O(n), where n is the size of s
        // Space: O(n)
        /*StringBuilder sb = new StringBuilder();

        for(char letter : s.toCharArray()) {
            if(Character.isLetterOrDigit(letter)) {
                sb.append(letter);
            }
        }

        String original = sb.toString();
        String reversed = sb.reverse().toString();

        return original.equalsIgnoreCase(reversed);*/

        // Time: O(n)
        // Space: O(1)
        /*int left = 0, right = s.length() - 1;
        while(left < right) {
            while(left < right && !Character.isLetterOrDigit(s.charAt(left))) {
                left++;
            }

            while(left < right && !Character.isLetterOrDigit(s.charAt(right))) {
                right--;
            }

            if(Character.toLowerCase(s.charAt(left)) != Character.toLowerCase(s.charAt(right))) {
                return false;
            }

            left++; right--;
        }

        return true;*/

        return isPalindromeRec(s, 0, s.length() - 1);
    }

    private boolean isPalindromeRec(String s, int left, int right) {
        // Time complexity: O(n)
        // Space complexity: O(n)
        if(left > right) {
            return true;
        }

        char leftChar = s.charAt(left);
        char rightChar = s.charAt(right);

        if(Character.isLetterOrDigit(leftChar) && Character.isLetterOrDigit(rightChar)) {
            if(Character.toLowerCase(leftChar) != Character.toLowerCase(rightChar)) {
                return false;
            }

            return isPalindromeRec(s, left + 1, right - 1);
        }

        if(!Character.isLetterOrDigit(leftChar)) {
            left++;
        }

        if(!Character.isLetterOrDigit(rightChar)) {
            right--;
        }

        return isPalindromeRec(s, left, right);



    }
}